local ChannelBase = import(".ChannelBase")
local ChannelMsdk = class("ChannelMsdk", ChannelBase)

local PLATFORM_WX = 1
local PLATFORM_QQ = 2
local PLATFORM_GUEST = 5


local UserWrapper = {
	eFlag_Succ = 0,		--成功
	eFlag_Error = -1,	--失败
	eFlag_Local_Invalid = -2,	--自动登陆失败，需重新登陆
	eFlag_NotInWhiteList = -3,	--不在白名单中
	eFlag_LbsNeedOpenLocationService = -4,	--游戏所需定位服务为开启
	eFlag_LbsLocateFail = -5,		--游戏定位失败
	
	-- 手Q相关
	eFlag_QQ_NoAcessToken = 1000,	--手Q登陆失败，未获取到accesstoken
	eFlag_QQ_UserCancel = 1001,		--玩家取消手Q授权登录
	eFlag_QQ_LoginFail = 1002,		--手Q登陆失败
	eFlag_Login_NetworkErr = 1003,	--网络错误
	eFlag_QQ_NotInstall = 1004,		--玩家设备未安装手Q客户端
	eFlag_QQ_NotSupportApi = 1005,	--玩家手Q客户端不支持此接口
	eFlag_QQ_AccessTokenExpired = 1006,	--accesstoken过期
	eFlag_QQ_PayTokenExpired = 1007,	--paytoken过期

	-- 微信相关
	eFlag_WX_NotInstall = 2000,		--玩家设备未安装微信客户端
	eFlag_WX_NotSupportApi = 2001,	--玩家微信客户端不支持此接口
	eFlag_WX_UserCancel = 2002,		--玩家取消微信授权登录
	eFlag_WX_UserDeny = 2003,		--玩家拒绝微信授权登录
	eFlag_WX_LoginFail = 2004,		--微信登录失败
	eFlag_WX_RefreshTokenSucc = 2005,	--微信刷新票据成功
	eFlag_WX_RefreshTokenFail = 2006,	--信刷新票据失败
	eFlag_WX_AccessTokenExpired = 2007,	--微信accessToken过期
	eFlag_WX_RefreshTokenExpired = 2008,--微信refreshtoken过期

	--异账号相关：
	eFlag_NeedLogin = 3001,	--游戏本地账号和拉起账号均无法登陆
	eFlag_UrlLogin = 3002,	--不存在异账号，游戏通过拉起账号快速登陆成功
	eFlag_NeedSelectAccount = 3003,	--游戏本地账号和拉起账号存在异账号
	eFlag_AccountRefresh = 3004,		--不存在异账号，MSDK已通过刷新接口将本地账号票据刷新

	eFlag_Need_Realname_Auth = 3005,
	eFlag_Checking_Token = 5001
}


function ChannelMsdk:ctor()
    self.super.ctor(self)
    self._noticeTime = 0
	self._friendCache = nil
	self._httpdnsCount = {}
	-- self.flagIsReview = false
	self._redirecturl = nil
	self._groupRetCallback = {}

end


function ChannelMsdk:_init()
    app:addCustomEventListener("CHANNEL_LOGIN_EVENT", function(event)
		local param = event:getUserStr()
		self:loginCallback(param)
	end)
	app:addCustomEventListener("CHANNEL_WAKEUP_EVENT", function(event)
		local param = event:getUserStr()
		self:wakeupCallback(param)
	end)

	app:addCustomEventListener("CHANNEL_PAY_EVENT", function(event)
		local param = event:getUserStr()
		self:payCallback(param)
	end)
	app:addCustomEventListener("CHANNEL_PAY_MP_EVENT", function(event)
		local param = event:getUserStr()
		self:payMPCallBack(param)
	end)
	app:addCustomEventListener("CHANNEL_SHARE_EVENT", function(event)
		local param = event:getUserStr()
		self:shareCallback(param)
	end)
	app:addCustomEventListener("CHANNEL_RELATION_EVENT", function(event)
		local param = event:getUserStr()
		self:relationCallback(param)
	end)
	app:addCustomEventListener("CHANNEL_HTTPDNS_EVENT", function(event)
		local param = event:getUserStr()
		self:httpdnsCallback(param)
	end)

	app:addCustomEventListener("CHANNEL_GUILD_EVENT", function(event)
		local param = event:getUserStr()
		self:groupCallback(param)
	end)
end

function ChannelMsdk:getGateHostFromConfig(msdkPlatform)
	local redirecturl =  app.configuration:getValue("GameHostRedirecturl")
	if redirecturl and redirecturl ~= "" then
		if string.sub(redirecturl,#redirecturl)~="/" then
			redirecturl = (redirecturl.."/")
		end
		return redirecturl
	end

    local wgPlatform = self:getWGPlatform()
	local strWgPlatform
	if msdkPlatform then
		strWgPlatform = msdkPlatform
	else
		if wgPlatform == Enums.MSDK_PLATFORM.QQ then
			strWgPlatform = "QQ"
		elseif wgPlatform == Enums.MSDK_PLATFORM.WX then
			strWgPlatform = "WX"
		else
			strWgPlatform = "QQ"
		end
	end
    
	local strGateHost = "GateHosts"..strWgPlatform

	-- ios 根据手机别名判断进入的服务器，主要用来测试
	local strTestPre = ""
	if app:isIOS() or app:isAndroid() then
		local phoneName = cc.GetPhoneName()
		if phoneName and phoneName ~= "" then
			if string.isEndWith(phoneName, "Wjyz2DTest") then
				strTestPre = "EmaQA"
			elseif string.isEndWith(phoneName, "Wjyz2DTencentTest") then
				strTestPre = "TXQA"
			elseif string.isEndWith(phoneName, "Wjyz2DTencentPre") then
				strTestPre = "TXPre"
			end
		end
	end

	local gateHosts
	if strTestPre ~= "" then
		gateHosts = app.configuration:getValue(strTestPre .. strGateHost)
	end
	if not gateHosts then
		gateHosts = app.configuration:getValue(strGateHost)
	end

    if gateHosts and string.sub(gateHosts,#gateHosts)~="/" then
        gateHosts = (gateHosts.."/")
    end

    return gateHosts
end


-- 请求 提审状态
-- function ChannelMsdk:requestReviewState(cb)
-- 	print("===========+>>> requestReviewState")
-- 	local host = self:getGateHostFromConfig("QQ")
-- 	local platform = self:getPlatform()
-- 	local version = app:getVersion().."."..app:getResVersion()
-- 	if platform ~= "ios" then
-- 		return
-- 	end
--     local url = host.."appleversion?".."os="..platform.."&version="..version
-- 	app.http.reqJsonData(url,function(decode,errorMsg,code)
-- 		dump(decode)
-- 		if code == 200 then
-- 			local param = decode.data
-- 			local msg = decode.msg
-- 			local ret = decode.ret
-- 			if ret == 0 and param then
-- 				if param.redirecturl then
-- 					self:setRedirecturl(param.redirecturl)
-- 					self:setIsReivew(true)
-- 				end
-- 			end
-- 		else
-- 			release_print("=========>Session:requestReviewState fail errorMsg, code", errorMsg, code)
-- 		end
-- 		if cb then
-- 			cb()
-- 		end
-- 	end,"POST",true)
-- end

function ChannelMsdk:_joinUrl(host)
    local openId = self:getOpenId()
    local pf = self:getPf()
    local pfKey = self:getPfKey()
    local guestAccessToken = self:getGuestAccessToken()
    local wxAccessToken = self:getWxAccessToken()
    local qqAccessToken = self:getQqAccessToken()
    local qqPayToken = self:getQqPayToken()
    local loginChannelId = self:getTencentLoginChannelId()
    local regChannelId = self:getRegChannelId()
	local channelTag = app:getChannelTag()
	local platform = self:getPlatform()
	local version = app:getVersion().."."..app:getResVersion()
    local channel = "tencent"

    local url = host.."gamelogin?".."openId="..openId

    if pf then
        url = url.."&pf="..pf
    end
    if pfKey then
        url = url.."&pfKey="..pfKey
    end

    if guestAccessToken and #guestAccessToken > 0 then
        url = url.."&guestAccessToken="..guestAccessToken
        channel = "txguest"
    end

    if wxAccessToken and #wxAccessToken > 0 then
        url = url.."&wxAccessToken="..wxAccessToken
        channel = "wx"
    end
    
    if qqAccessToken and #qqAccessToken > 0 then
        url = url.."&qqAccessToken="..qqAccessToken
        channel = "qq"
    end
    if qqPayToken and #qqPayToken > 0 then
        url = url.."&qqPayToken="..qqPayToken
    end

    url=url.."&channel="..channel
    url=url.."&channeltag="..channelTag
    url=url.."&loginchannel="..loginChannelId
	url=url.."&regchannel="..regChannelId
	url=url.."&os="..platform
	url=url.."&version="..version

	print("---------------msdk ChannelMsdk:jointUrl()",url)
    return url
end

function ChannelMsdk:getServerList(cb)
    
end

function ChannelMsdk:_login()

	local flag = self:getWakeupFlagBeforeLoginFlag()
	if flag == UserWrapper.eFlag_NeedSelectAccount then
		-- 异账号时，游戏需要弹出提示框让用户选择需要登陆的账号
		scheduler.newCron(function()
			local confirmDialog = display.newConfirmDialog(L("tips_3000143"),
			function()
				self:setWakeupFlagBeforeLoginFlag(-1)
				self:switchUser(true)
				self._isWakeUpFromBeforeLogin = true
			end,
			function()
				self:setWakeupFlagBeforeLoginFlag(-1)
				self:_login()
			end)
			confirmDialog:setConfirmText(L("tips_3000138"))
			confirmDialog:setCancelText(L("tips_3000121"))
			cc.Director:getInstance():getRunningScene():addChild(confirmDialog, 1000)
		end, 0.05)
		return
	end

    local ok=nil
	if app:isAndroid() then
		ok= self.callJava("()V", "login")
	elseif app:isIOS() then
		ok = self.callOC("login")
	end

	if not ok then
        self:_onLoginFail()
	end
end

function ChannelMsdk:_logout()
    if app:isAndroid() then
		self.callJava("()V", "logout")
	elseif app:isIOS() then
		self.callOC("logout")
    end
	app.session:clearLogined()
	self._isIgnoreWakeUpFrom = true
	self:_onLogoutSuccess()
	EM:notify("OnGameLogout")
end

function ChannelMsdk:_switchAccount()
    self:_logout()
end

-- 是否是提审状态
-- function ChannelMsdk:isReview()
--     return self.flagIsReview
-- end

-- 设置提审状态
-- function ChannelMsdk:setIsReivew(flagIsReview)
-- 	self.flagIsReview = flagIsReview
-- end

-- params = {count=, goodsUrl=, isGameCoin=, produncId=}
-- count 数量 android/ios（有更多的意思）
-- goodsUrl 直购url android直购
-- isGameCoin 是否托管游戏币 ios
-- produncId 商品id ios
function ChannelMsdk:_pay( params )
	local ok=nil

	local zoneId = app.session:getZoneId()
	params.zoneId = zoneId .. "_" .. UD.player.uid
    params.count = params.count .. ""

	if app:isAndroid() then
		ok = self.callJava("(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "pay",
			params.zoneId, params.count, params.goodsUrl or "")
	elseif app:isIOS() then
	    if params.isGameCoin == nil then
	    	params.isGameCoin = true
	    end
		ok = self.callOC("pay", params)
	end

	dump(params, "ChannelMsdk.pay params")

	if not ok then
		self:_onPayFail()
	end
end

function ChannelMsdk:_share(type, title, desc, imgPath)
    local ok=nil
	if app:isAndroid() then
		ok = self.callJava("(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "share", type, title, desc, imgPath)
	elseif app:isIOS() then
		local args = {type=type, title=title, desc=desc, path=imgPath}
		ok = self.callOC("share", args)
	end
	if not ok then
		self:_onShareFail()
	end
end

-- reqType 	类型 "mp"（获取营销活动）"friendspay"（好友代付）
function ChannelMsdk:getPayMPInfo(reqType)
	local ok=nil
	local zoneId = app.session:getZoneId() .. "_" .. UD.player.uid
	reqType = reqType or "mp"

	print("ChannelMsdk.getPayMPInfo", reqType, zoneId)

	if app:isAndroid() then
		ok = self.callJava("(Ljava/lang/String;Ljava/lang/String;)V", "getPayMPInfo",
			reqType, tostring(zoneId))
	elseif app:isIOS() then
		local params = {reqType=reqType, zoneId=zoneId, isGameCoin=true}
		ok = self.callOC("getPayMPInfo", params)
	end
end

function ChannelMsdk:getChannelTag()
	return app:getChannelTag()
end

function ChannelMsdk:getChannelId()
	local guestAccessToken = self:getGuestAccessToken()
	local wxAccessToken = self:getWxAccessToken()
	local qqAccessToken = self:getQqAccessToken()
	local channel = "tencent"
	if guestAccessToken and #guestAccessToken > 0 then
	    channel = "txguest"
	end

	if wxAccessToken and #wxAccessToken > 0 then
	    channel = "wx"
	end
	if qqAccessToken and #qqAccessToken > 0 then
	    channel = "qq"
	end
	return channel
end

function ChannelMsdk:getAccessToken()
	local platform = self:getWGPlatform()
	local accessToken = ""
	if platform == PLATFORM_WX then
		accessToken = self:getWxAccessToken()
	elseif platform == PLATFORM_QQ then
		accessToken = self:getQqAccessToken()
	elseif platform == PLATFORM_GUEST then
		accessToken = self:getGuestAccessToken()
	end
	return accessToken
end

function ChannelMsdk:getGuestAccessToken()
	local ok , ret
	if app:isIOS() then
		ok , ret = self.callOC("getGuestAccessToken")
	end
	return ret
end

function ChannelMsdk:getWxAccessToken()
	local ok , ret
	if app:isAndroid() then
		ok , ret = self.callJava("()Ljava/lang/String;", "getWxAccessToken")
	elseif app:isIOS() then
		ok , ret = self.callOC("getWxAccessToken")
	end
	return ret
end

function ChannelMsdk:getQqAccessToken()
	local ok , ret
	if app:isAndroid() then
		ok , ret = self.callJava("()Ljava/lang/String;", "getQqAccessToken")
	elseif app:isIOS() then
		ok , ret = self.callOC("getQqAccessToken")
	end
	return ret
end

function ChannelMsdk:getQqPayToken()
	local ok, ret
	if app:isAndroid() then
		ok, ret = self.callJava("()Ljava/lang/String;", "getQqPayToken")
	elseif app:isIOS() then
		ok, ret = self.callOC("getQqPayToken")
	end
	return ret
end


function ChannelMsdk:getRegChannelId()
	local ok , ret
	if app:isAndroid() then
		ok,ret = self.callJava("()Ljava/lang/String;", "getRegChannelId")
	elseif app:isIOS() then
		ok,ret = self.callOC("getRegChannelId")
	end
	if not ok then
		return "unknow"
	end
	return ret
end


function ChannelMsdk:getLoginChannelId()
	local ok , ret
	if app:isAndroid() then
		ok,ret = self.callJava("()Ljava/lang/String;", "getLoginChannelId")
	elseif app:isIOS() then
		ok,ret =  self.callOC("getLoginChannelId")
	end
	if not ok then
		return "unknow"
	end
	return ret
end


function ChannelMsdk:getWGPlatform()
	local ok, ret
	if app:isAndroid() then
		ok, ret = self.callJava("()I","getPlatform")
	elseif app:isIOS() then
		ok, ret = self.callOC("getPlatform")
	end
	if not ok then
		return 0
	end
	return ret
end


function ChannelMsdk:getOpenId()
	local ok , ret
	if app:isAndroid() then
		ok , ret = self.callJava("()Ljava/lang/String;", "getOpenId")
	elseif app:isIOS() then
		ok , ret = self.callOC("getOpenId")
	end

	if not ok then
		return "NONE"
	end
	return ret
end

function ChannelMsdk:getAccount()
	return self:getOpenId()
end

function ChannelMsdk:getPf()
	local ok, ret
	if app:isAndroid() then
		ok, ret =  self.callJava("()Ljava/lang/String;", "getPf")
	elseif app:isIOS() then
		ok, ret =  self.callOC("getPf")
	end
	return ret
end

function ChannelMsdk:getPfKey()
	local ok , ret
	if app:isAndroid() then
		ok , ret =  self.callJava("()Ljava/lang/String;", "getPfKey")
	elseif app:isIOS() then
		ok , ret =  self.callOC("getPfKey")
	end
	return ret
end

-- 获取平台支付授权参数
function ChannelMsdk:getMidasPermissionParams()
	local params = {}
	local openKey
	local platform = self:getWGPlatform()
	if platform == PLATFORM_WX then
		openKey = self:getWxAccessToken()
	elseif platform == PLATFORM_QQ then
		openKey = self:getQqPayToken()
	elseif platform == PLATFORM_GUEST then
		openKey = self:getGuestAccessToken()
	end
	params.openKey = openKey or ""
	params.pf = self:getPf() or ""
	params.pfKey = self:getPfKey() or ""

	dump(params, "getMidasPermissionParams")
	return params
end


function ChannelMsdk:openURL(url, dir)
	-- 防止多次点击 openurl 
	local nowTime = app.session:getServerTime()
	if self._openUrlTime then
		if nowTime - self._openUrlTime <= 2 then
			return
		end
	end
	self._openUrlTime = nowTime

	if not dir then
		dir = 0
	end
	if app:isAndroid() then
		self.callJava("(Ljava/lang/String;I)V", "openURL", url, dir)
	elseif app:isIOS() then
		self.callOC("openURL", {url=url, dir=dir})
	end
end

function ChannelMsdk:openWeiXinDeeplink(url)
	if PLATFORM_WX == self:getWGPlatform() then
		if app:isAndroid() then
			self.callJava("(Ljava/lang/String;)V", "openWeiXinDeeplink", url)
		elseif app:isIOS() then
			self.callOC("openWeiXinDeeplink", {url=url})
		end
	end
end

function ChannelMsdk:showNotice(id)
	local ok = false
	if app:isAndroid() then
		ok = self.callJava("(Ljava/lang/String;)V", "showNotice",id)
	elseif app:isIOS() then
		ok = self.callOC("showNotice",{id=id})
	end
	print("ChannelMsdk.showNotice", ok)
end


function ChannelMsdk:getNoticeContent(id)
	local ok = false
	local ret = ""
	if app:isAndroid() then
		ok , ret = self.callJava("(Ljava/lang/String;)Ljava/lang/String;", "getNoticeContent",id)
	elseif app:isIOS() then
		ok , ret = self.callOC("getNoticeContent",{id=id})
	end
	if not ok then
		ret = ""
	end
	return ret
end


-- 直接调用拉取好友接口，里面有自己
function ChannelMsdk:queryMyInfo()
	if not self:isLogin() then
		return
	end
	self:_initFriendCache()
	if not self._friendCache or not self._friendCache.myInfo then
		if app:isAndroid() then
			self.callJava("()V", "queryMyInfo")
		elseif app:isIOS() then
			self.callOC("queryMyInfo")
		end
	else
		return self._friendCache.myInfo
	end
end

function ChannelMsdk:queryGameFriendsInfo()
	if not self:isLogin() then
		return
	end
	self:_initFriendCache()
	if not self._friendCache or not self._friendCache.friendsInfo then
		if app:isAndroid() then
			self.callJava("()V", "queryGameFriendsInfo")
		elseif app:isIOS() then
			self.callOC("queryGameFriendsInfo")
		end
	else
		return self._friendCache.friendsInfo
	end
end

function ChannelMsdk:addGameFriendToQQ(openId, desc, msg)
	if app:isAndroid() then
		self.callJava("(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "addGameFriendToQQ", openId, desc, msg)
	elseif app:isIOS() then
		self.callOC("addGameFriendToQQ",{openId=openId, desc=desc, msg=msg})
	end
end

function ChannelMsdk:setPushTag(tag)
	local ok
	if app:isAndroid() then
		ok = self.callJava("(Ljava/lang/String;)V", "setPushTag", tag)
	elseif app:isIOS() then
		ok = self.callOC("setPushTag",{tag=tag})
	end
	print("ChannelMsdk.setPushTag tag = " .. tag, ok and "succ" or "fail")
end

function ChannelMsdk:deletePushTag(tag)
	local ok
	if app:isAndroid() then
		ok = self.callJava("(Ljava/lang/String;)V", "deletePushTag", tag)
	elseif app:isIOS() then
		ok = self.callOC("deletePushTag",{tag=tag})
	end
	print("ChannelMsdk.deletePushTag tag = " .. tag, ok and "succ" or "fail")
end

function ChannelMsdk:enterUserCenter()

end


function ChannelMsdk:savePushData(params)
	if not params then
		return
	end

	local title = params.title
	local titleType = params.titleType or 1
	local content = params.msg
	local time = TimeUtil.getNextTargetTimeStamp(params.time)

	-- dump(params, "savePushData")
	-- print("savePushData.time", time)

	if app:isAndroid() then
		self.callJava("(Ljava/lang/String;ILjava/lang/String;I)V", "addLocalNotification",title,titleType,content,time)
	elseif app:isIOS() then
		self.callOC("addLocalNotification",{time=time, content=content})
	end
end

function ChannelMsdk:deletePushData( )
	if app:isAndroid() then
		self.callJava("()V", "clearLocalNotification")
	elseif app:isIOS() then
		self.callOC("clearLocalNotification")
	end
end

-- httpdns
function ChannelMsdk:getHostByNameAsync(dns, cb)
	if not dns or not cb then
		executeFunc(cb)
		return
	end

	self._domainCache = dns
	self._httpdnsCallback = cb

	dump(dns, "httpdns getHostByNameAsync------>>>>")
	if app:isAndroid() then
		self.callJava("(Ljava/lang/String;)V", "getAddrByName", dns)
	elseif app:isIOS() then
		self.callOC("getHostByNameAsync", {domain = dns})
	end
end

function ChannelMsdk:isLogin()
	if app:isAndroid() then
		local ok , ret = self.callJava("()Z", "isLogin")
		return ret
	elseif app:isIOS() then
		local ok , ret = self.callOC("isLogin")
		return ret
	end
	return false
end

function ChannelMsdk:isWakeUpFromQQ()
	local ok = false
	local ret = false
	if app:isAndroid() then
		ok, ret = self.callJava("()Z","isWakeUpFromQQ")
	elseif app:isIOS() then
		ok, ret = self.callOC("isWakeUpFromQQ")
	end
	return ret
end

function ChannelMsdk:isWakeUpFromWX()
	local ok = false
	local ret = false
	if app:isAndroid() then
		ok, ret = self.callJava("()Z","isWakeUpFromWX")
	elseif app:isIOS() then
		ok, ret= self.callOC("isWakeUpFromWX")
	end
	return ret
end

-- 获取重哪里唤起的
function ChannelMsdk:getWakeUpFrom()
	if PLATFORM_WX == self:getWGPlatform() then
		if self:isWakeUpFromWX() then
			return Enums.WAKE_UP.WXGAME
		end
	elseif PLATFORM_QQ == self:getWGPlatform() then
		if self:isWakeUpFromQQ() then
			return Enums.WAKE_UP.QQGAME
		end
	end
	return Enums.WAKE_UP.NONE
end


function ChannelMsdk:getAppId()
	local appId, ok
	if app:isAndroid() then
		if PLATFORM_WX == self:getWGPlatform() then
			ok , appId = self.callJava("()Ljava/lang/String;","getWXAppId")
		elseif PLATFORM_QQ == self:getWGPlatform() then
			ok , appId = self.callJava("()Ljava/lang/String;", "getQQAppId")
		end
	elseif app:isIOS() then
		if PLATFORM_WX == self:getWGPlatform() then
			ok , appId = self.callOC("getWXAppId")
		elseif PLATFORM_QQ == self:getWGPlatform() then
			ok , appId = self.callOC("getQQAppId")
		end
	end

	if not appId then
		appId = ""
	end
	return appId
end

function ChannelMsdk:getMsdkKey()
	local msdkKey, ok
	if app:isAndroid() then
		ok , msdkKey = self.callJava("()Ljava/lang/String;", "getMsdkKey")
	elseif app:isIOS() then
		ok , msdkKey = self.callOC("getMsdkKey")
	end
	if not msdkKey then
		msdkKey = ""
	end
	return msdkKey
end

-- 自定义数据上报
-- param name 		事件名字
-- param paramStr 	事件参数 param1|param2|param3
-- param isRealTime 是否实时上传
function ChannelMsdk:reportEvent(name, paramStr, isRealTime)
	if app:isAndroid() then
		local ok = self.callJava("(Ljava/lang/String;Ljava/lang/String;Z)V", "reportEvent", name, paramStr, isRealTime)
	elseif app:isIOS() then
		local ok = self.callOC("reportEvent", {name=name, param=paramStr, isRealTime=isRealTime})
	end
end

-- 协议打开浏览器
function ChannelMsdk:WGOpenFullScreenWebViewWithJson(jsonStr)
	print("WGOpenFullScreenWebViewWithJson", jsonStr)
	if app:isAndroid() then
		local ok = self.callJava("(Ljava/lang/String;)V", "WGOpenFullScreenWebViewWithJson", jsonStr)
	elseif app:isIOS() then
		local ok = self.callOC("WGOpenFullScreenWebViewWithJson", {jsonStr=jsonStr})
	end
end

-- 健康中控数据上报
function ChannelMsdk:WGReportPrajna(serialNumber)
	print("WGReportPrajna", serialNumber)
	if app:isAndroid() then
		local ok = self.callJava("(Ljava/lang/String;)V", "WGReportPrajna", serialNumber)
	elseif app:isIOS() then
		local ok = self.callOC("WGReportPrajna", {serialNumber=serialNumber})
	end
end

-- 处理异账号登陆
function ChannelMsdk:switchUser(isLaunchUser, callback)
	local ok, ret
	if app:isAndroid() then
		ok, ret = self.callJava("(Z)Z", "switchUser", isLaunchUser)
	elseif app:isIOS() then
		ok, ret = self.callOC("switchUser", {isLaunchUser=isLaunchUser})
	end
	print("=============+>>> switchUser", isLaunchUser, ret)
	if not isLaunchUser then
		if not ret then
			app:relaunchApp()
		end
	else
		if ret then
			if app.session and app.session:isLogined() then
				self:logout()
				app:relaunchApp()
			end
		else
			local isLogined = app.session and app.session:isLogined()
			self:logout()
			self._isIgnoreWakeUpFrom = nil
			if isLogined then
				app:relaunchApp()
			else
				self:showLoginView()
			end
		end
	end
	if callback then
		callback()
	end
end



function ChannelMsdk:getLoginNotice()
	return self:getNoticeContent("563")
end

function ChannelMsdk:getLoginZoneNotice()
	return self:getNoticeContent("883")
end

function ChannelMsdk:getLoginedNotice()
	return self:getNoticeContent("603")
end

function ChannelMsdk:_getGlobalNoticeContent()
	return self:getNoticeContent("564")
end



function ChannelMsdk:shareToFriend(cb, openId, title, desc, ext)
    self._shareCallback = cb
	local param
	if Enums.MSDK_PLATFORM.QQ == self:getWGPlatform() then
		local dataObj = {}
		dataObj.act = 1 -- 1  
		dataObj.friendOpenId = openId
		dataObj.title = title
		dataObj.desc = desc
		dataObj.gameTag = "MSG_HEART_SEND"
		--[[
			MSG_INVITE                //邀请
			MSG_FRIEND_EXCEED       //超越炫耀
			MSG_HEART_SEND          //送心
			MSG_SHARE_FRIEND_PVP    //PVP对战
		]]
		dataObj.msdkExtInfo = ext --游戏自定义透传字段，通过分享结果shareRet.extInfo返回给游戏，游戏可以用extInfo区分request
		dataObj.previewText = title
		dataObj.imageUrl = "http://qzonestyle.gtimg.cn/open_proj/proj_open_v2/ac/home/qrcode.jpg"
		dataObj.targetUrl = "http://qzonestyle.gtimg.cn/open_proj/proj_open_v2/ac/home/qrcode.jpg"
		param = dataObj
	elseif Enums.MSDK_PLATFORM.WX == self:getWGPlatform() then
		dataObj.friendOpenId = openId
		dataObj.title = title
		dataObj.desc = desc
		dataObj.mediaId = "" --图片的id 通过uploadToWX接口获取
		dataObj.mediaTagName = "MSG_INVITE"
		--[[
			"MSG_INVITE";                   // 邀请
			"MSG_SHARE_MOMENT_HIGH_SCORE";    //分享本周最高到朋友圈
			"MSG_SHARE_MOMENT_BEST_SCORE";    //分享历史最高到朋友圈
			"MSG_SHARE_MOMENT_CROWN";         //分享金冠到朋友圈
			"MSG_SHARE_FRIEND_HIGH_SCORE";     //分享本周最高给好友
			"MSG_SHARE_FRIEND_BEST_SCORE";     //分享历史最高给好友
			"MSG_SHARE_FRIEND_CROWN";          //分享金冠给好友
			"MSG_friend_exceed"         // 超越炫耀
			"MSG_heart_send"            // 送心
		]]
		dataObj.messageExt = "" --游戏分享是传入字符串，通过此消息拉起游戏会通过 OnWakeUpNotify(WakeupRet ret)中ret.messageExt回传给游戏
		dataObj.msdkExtInfo = ext --游戏自定义透传字段，通过分享结果shareRet.extInfo返回给游戏
		param = dataObj
	end
	print("=====>>>>  ", param)
	if not param then
		return
	end

	local ok=nil
	if app:isAndroid() then
		param = json.encode(param)
		if param then
			ok = self.callJava("(Ljava/lang/String;)V", "shareToFriend", param)
		end
	elseif app:isIOS() then
		ok =  self.callOC("shareToFriend", param)
	end
	
	if not ok then
        self:_onShareFail()
	end
end

function ChannelMsdk:inviteFriend(cb)
	local platformEnum =  self:getWGPlatform()
	if not self:isPlatformInstalled(platformEnum) then
		local str = ""
		if platformEnum == Enums.MSDK_PLATFORM.QQ then
			display.pushToast("未安装手Q") --@ignore
		elseif platformEnum == Enums.MSDK_PLATFORM.WX then
			display.pushToast("未安装微信") --@ignore
		end
		return;
	end

    self._shareCallback = cb
	local param
	local fileUtil = cc.FileUtils:getInstance()
	local imagePath = "" -- 当为""使用app icon 
	if Enums.MSDK_PLATFORM.QQ == self:getWGPlatform() then
		local dataObj = {}
		dataObj.qqScene = 2 -- 1  
		dataObj.title = L("无尽远征") --@ignore
		dataObj.desc = L("TencentAppShareMsgContent") --@ignore
		dataObj.url = string.format("http://gamecenter.qq.com/gcjump?appid=1105873472&pf=invite&from=androidqq&plat=qq&originuin=%s&ADTAG=gameobj.msg_invite", self:getOpenId())
		-- android qq 要求传url 或者 本地路径
		dataObj.imagePath = imagePath
		param = dataObj
	elseif Enums.MSDK_PLATFORM.WX == self:getWGPlatform() then
		local dataObj = {}
		dataObj.mediaTagName = "MSG_INVITE" -- 1  
		dataObj.title = L("无尽远征") --@ignore
		dataObj.desc = L("TencentAppShareMsgContent") --@ignore
		dataObj.messageExt = ""
		dataObj.imagePath = imagePath
		param = dataObj
	end
	print("=====>>>>  ", param)
	if not param then
		return
	end
	local ok=nil
	if app:isAndroid() then
		-- local newPath = app:getStorePath().."/tencent_invite_icon.png"
		-- local d = fileUtil:getDataFromFile(param.imagePath)
		-- if not d then
		-- 	return
		-- end
		-- fileUtil:writeDataToFile(d, newPath)

		-- param.imagePath = newPath
		param = json.encode(param)
		if param then
			ok = self.callJava("(Ljava/lang/String;)V" ,"shareTo", param)
		end
	elseif app:isIOS() then
		ok = self.callOC("shareTo", param)
    end

    if not ok then
        self:_onShareFail()
	end
end


function ChannelMsdk:tick(dt)
	local curtime = app:getTime()
	if curtime-self._noticeTime >= 60 then
		self._noticeTime = curtime
		local content = self:_getGlobalNoticeContent()
		if type(content)=="string" and content~="" then
			EM:notify("OnReciveNoticeFromMSDK",content)
		end
	end
end



function ChannelMsdk:_getFirstRealCachePath()
	local openId = self:getOpenId()
	local name = "realname_" .. openId
	return app:getStorePath() .. "/" .. name .. ".json", name
end

function ChannelMsdk:_saveRealNameCache()
	if self._firstRealNameInfo then
		local jsonStr = json.encode(self._firstRealNameInfo)
		if jsonStr then
			local path, name = self:_getFirstRealCachePath()
			print("save real name cache", path)
			io.writefile(path, jsonStr)
		end
	end
end

-- 检测用户首次使用实名帐号登录游戏后弹框实名确认
function ChannelMsdk:getFirstRealPopUpInfo(isBlock)
	if not self:isLogin() then
		return
	end
	-- 检查是否有缓存
	if self._firstRealNameInfo then
		return self._firstRealNameInfo
	end

	-- 有缓存
	local path, name = self:_getFirstRealCachePath()
	if io.exists(path) then
		local content = cc.FileUtils:getInstance():getStringFromFile(path)
		local realNameCache = json.decode(content)
		if realNameCache then
			self._firstRealNameInfo = realNameCache
			return self._firstRealNameInfo
		end
	end
	-- 查询msdk 后台接口
	local url
	local appId = self:getAppId()
	local msdkKey = self:getMsdkKey()
	local openId = self:getOpenId()

	local timestamp = os.time()
	local key = msdkKey..timestamp
	local sig = cc.Crypto:MD5(key, false)

	local postData
	local domain = self:getMsdkDomain()
	if PLATFORM_QQ == self:getWGPlatform() then
		url = string.format("/profile/qqget_first_reg?timestamp=%s&appid=%s&sig=%s&openid=%s&encode=2", 
		timestamp, appId, sig, openId)
		postData = json.encode({accessToken = self:getQqAccessToken()})
	elseif PLATFORM_WX == self:getWGPlatform() then
		url = string.format("/profile/wxget_first_reg?timestamp=%s&appid=%s&sig=%s&openid=%s&encode=2", 
		timestamp, appId, sig, openId)
		postData = json.encode({accessToken = self:getWxAccessToken()})
	end
	print("http ===> ", url, postData)
	if not url then
		return nil
	end
	url = domain..url
	
	app.http.reqJsonData(url,function(response,errorMsg,code)
		if response and response.ret == 0 then
			local isPop = tonumber(response.need_pop or "0") == 1
			local isRealName = tonumber(response.realname_flag or "0") == 1
			if isRealName then
				self._firstRealNameInfo = {isNeedPop = isPop, isRealName = isRealName}
				self:_saveRealNameCache()
			end
		else
			if response and response.msg then
				release_print(response.msg)
			end
		end
	end,"POST",isBlock, postData, true)

	return self._firstRealNameInfo
end
-- 
function ChannelMsdk:checkIsRealName()
	local firstRealNameInfo  = self:getFirstRealPopUpInfo()
	if firstRealNameInfo then
		return firstRealNameInfo.isRealName
	end
	return false
end

function ChannelMsdk:checkIsNeedPopFirstRealName()
	local firstRealNameInfo  = self:getFirstRealPopUpInfo()
	if firstRealNameInfo then
		return firstRealNameInfo.isNeedPop
	end
	return false
end

function ChannelMsdk:setFirstRealNamePopUp()
	if self._firstRealNameInfo and self._firstRealNameInfo.isNeedPop == true then
		self._firstRealNameInfo.isNeedPop = false
		self:_saveRealNameCache()
	end
end


function ChannelMsdk:_loginWithGuest()
	local ok=nil
	if app:isIOS() then
		ok = self.callOC("loginWithGuest")
	end
	if not ok then
		if self.loginCB then
			self.loginCB(self,"fail")
			self.loginCB=nil
		end
	end
end

function ChannelMsdk:_loginWithWX()
	local ok=nil
	if app:isAndroid() then
		ok = self.callJava("()V","loginWithWX")
	elseif app:isIOS() then
		ok = self.callOC("loginWithWX")
	end

	if not ok then
		if self.loginCB then
			self.loginCB(self,"fail")
			self.loginCB=nil
		end
	end
end

function ChannelMsdk:_loginWithQQ()
	local ok=nil
	if app:isAndroid() then
		ok =  self.callJava("()V", "loginWithQQ")
	elseif app:isIOS() then
		ok =  self.callOC("loginWithQQ")
	end

	if not ok then
		if self.loginCB then
			self.loginCB(self,"fail")
			self.loginCB=nil
		end
	end
end




function ChannelMsdk:loginCallback(code)
	local codeNum = tonumber(code)
	release_print("---------------msdk ChannelMsdk:loginCallback",code)
	local result = "fail"
	if codeNum == UserWrapper.eFlag_Succ then
		result = "success"
	elseif codeNum == UserWrapper.eFlag_WX_RefreshTokenSucc or
		codeNum == UserWrapper.eFlag_AccountRefresh then
		-- 微信自动刷新票据成功
		-- 不存在异账号，MSDK已通过刷新接口将本地账号票据刷新
		-- 票据刷新成功要通知服务器
		app:setMidasPermissionOK(true)
		return
	elseif codeNum == UserWrapper.eFlag_QQ_UserCancel then
		display.pushToast(L("取消QQ登录"))
	elseif codeNum == UserWrapper.eFlag_QQ_LoginFail then
	elseif codeNum == UserWrapper.eFlag_WX_LoginFail then
	elseif codeNum == UserWrapper.eFlag_WX_NotInstall then
		-- 扫二维码登陆
		return
	elseif codeNum == UserWrapper.eFlag_WX_NotSupportApi then
		display.pushToast(L("tips_3000158"))
	elseif codeNum == UserWrapper.eFlag_WX_UserCancel then
		display.pushToast(L("tips_3000160"))
	elseif codeNum == UserWrapper.eFlag_WX_UserDeny then
		display.pushToast(L("tips_3000159"))
	elseif codeNum == UserWrapper.eFlag_NeedLogin then

	elseif codeNum == UserWrapper.eFlag_Local_Invalid then
		-- 自动登录失败显示登录界面
	end

	if self._view then
		if result == "success" then
			GemService:SetEvent(4, true, "success", false, false)
		else
			GemService:SetEvent(4, false, code, false, false)
		end
	end
    -- 
	self:queryMyInfo()
	self:queryGameFriendsInfo()
	self._firstRealNameInfo = nil
    self:getFirstRealPopUpInfo()
	self._isChannelIdFromTencent = nil
	self._tencentLoginChannelId = nil
	self:isChannelIdFromTencent()
	
	if codeNum ~= UserWrapper.eFlag_Local_Invalid then
		self:setLastWakeUpPlatform(-1)
	end

	if result == "success" then
		local wgPlatform = self:getWGPlatform()
		if wgPlatform == Enums.MSDK_PLATFORM.WX then
			display.pushToast(L("微信登录成功"))
		elseif wgPlatform == Enums.MSDK_PLATFORM.QQ then
			display.pushToast(L("QQ登录成功"))
		end
        self:hideLoginView()
        self:_onLoginSuccess()
    else
		if not self:isLogin() then
			print("app.session:isLogined()", app.session:isLogined())
			if app.session:isLogined() then
				scheduler.newCron(function()
					local str = ""
					if codeNum == UserWrapper.eFlag_Error then
						str = L("授权过期，请重新登录")
					else
						str = L("tipsLoginSomewhereElse")
					end
					local messageBox = display.newMessageBox(str,
						function()
							self:setLastWakeUpPlatform(self:getWGPlatform())
							self:logout(function()
								app:relaunchApp()
							end)
						end)
					cc.Director:getInstance():getRunningScene():addChild(messageBox, 1000)
				end, 0.05)
			else
				self:showLoginView()
			end
        end
        self:_onLoginFail()
	end
end

function ChannelMsdk:hideLoginView()
	if self._view then
		self._view:removeFromParent()
		self._view = nil
	end
end

function ChannelMsdk:showLoginView()
	if self._isIgnoreWakeUpFrom then
		self:_realShowLoginView()
	else
		local platform = self:_getWakeUpFromPlatform()
		print("==============>>>>> platform :", platform)
		if platform == PLATFORM_WX then
			self:_loginWithWX()
		elseif platform == PLATFORM_QQ then
			self:_loginWithQQ()
		else
			self:_realShowLoginView()
		end
	end
	self._isIgnoreWakeUpFrom = nil
end

function ChannelMsdk:_realShowLoginView()
	if not self._view then
		local view = require("app.login.views.TencentLoginView").new()
		local scene = cc.Director:getInstance():getRunningScene()
		if cc.isAlive(scene:findChild("HotFixScene/hotfix")) then
			scene:findChild("HotFixScene/hotfix"):addChild(view, 1000)
		else
			scene:addChild(view, 1000)
		end
		self._view = view

		view:onOperate(function(op, sender)
			if op == "guest" then
				self:_loginWithGuest()
			elseif op == "qq" then
				self:_loginWithQQ()
			elseif op == "wx" then
				self:_loginWithWX()
			end
			GemService:SetEvent(3, true, string.upper(op), true, false)

			sender:enableButtons(false)
		end)
	end
	self._view:setVisible(true)
	self._view:enableButtons(true)
end


function ChannelMsdk:wakeupCallback(jsonRetStr)
	local wakeUpRet
	print("-----msdk ChannelMsdk:wakeupCallback json", jsonRetStr)
	
	local isJson = false
	if jsonRetStr then
		local retNum = tonumber(jsonRetStr)
		if not retNum then
			isJson = true
			wakeUpRet = json.decode(jsonRetStr)
			if not wakeUpRet then
				wakeUpRet = {}
			end
		else
			wakeUpRet = {}
			wakeUpRet.flag = retNum
		end
	else
		wakeUpRet = {}
	end
	
	dump(wakeUpRet, "-----msdk ChannelMsdk:wakeupCallback wakeUpRet")
	local code = tonumber(wakeUpRet.flag)
	release_print("-----msdk ChannelMsdk:wakeupCallback", code)

	if code == UserWrapper.eFlag_Succ or code == UserWrapper.eFlag_AccountRefresh then
		-- eFlag_AccountRefresh代表 刷新微信票据成功
	elseif code == UserWrapper.eFlag_UrlLogin then
		-- 用拉起的账号登录，登录结果在OnLoginNotify()中回调
	elseif code == UserWrapper.eFlag_NeedSelectAccount then
		-- 异账号时，游戏需要弹出提示框让用户选择需要登陆的账号
		scheduler.newCron(function()
			local confirmDialog = display.newConfirmDialog(L("tips_3000143"),
			function()
				self:switchUser(true)
			end,
			function() 
				self:switchUser(false)
			end)
			confirmDialog:setConfirmText(L("tips_3000138"))
			confirmDialog:setCancelText(L("tips_3000121"))
			cc.Director:getInstance():getRunningScene():addChild(confirmDialog, 1000)
		end, 0.05)
	elseif code == UserWrapper.eFlag_NeedLogin then
		if app.session and app.session:isLogined() then
			-- 需要登录的唤醒，需要在ralaunchApp之后主动拉起平台授权登录
			if not isJson then
				-- 支付需要登录时，重登里需要自动授权
				if app:isIOS() then
					scheduler.newCron(function()
						local messageBox = display.newMessageBox(L("授权过期，请重新登录"),
							function()
								self:setLastWakeUpPlatform(self:getWGPlatform())
								self:logout(function()
									app:relaunchApp()
								end)
							end)
						cc.Director:getInstance():getRunningScene():addChild(messageBox, 1000)
					end, 0.05)
				else
					self:setLastWakeUpPlatform(self:getWGPlatform())
					self:logout(function()
						app:relaunchApp()
					end)
				end
			else
				app:relaunchApp()
			end
		else
			self:showLoginView()
		end
	else
		app:relaunchApp()
	end
	
	self._isWakeUpFromBeforeLogin = nil
	if app.session and app.session:isLogined() then
		EM:notify("onWakeUpChange")
	end
end


-- code = -1, 支付出错
-- code = 0, 支付成功
-- code = 2, 用户取消
function ChannelMsdk:payCallback(code)
	code = tonumber(code)
	release_print("-----msdk ChannelMsdk:payCallback",code)
    if code == Enums.PayRetState.success then
        self:_onPaySuccess()
	else
		if code == 2 then
			code = Enums.PayRetState.cancel
		else
			code = Enums.PayRetState.fail
		end
        self:_onPayFail(code)
    end
end

-- 获取支付营销活动回调
function ChannelMsdk:payMPCallBack(jsonStr)
	local mpInfo
	if jsonStr and jsonStr ~= "" then
		mpInfo = json.decode(jsonStr)
		if mpInfo and mpInfo.ret ~= 0 then
			mpInfo = nil
		end
	end

	release_print("-----msdk ChannelMsdk:payMPCallBack", mpInfo and mpInfo.ret)
	-- print("-----msdk ChannelMsdk:payMPCallBack", jsonStr)
	-- dump(mpInfo, "-----msdk ChannelMsdk:payMPCallBack", 10)

	EM:notify("onPayMPInfoUpdate", mpInfo)
end

function ChannelMsdk:shareCallback(code)
	code = tonumber(code)
	print("-----msdk ChannelMsdk:shareCallback", code)

	local result = "fail"
	if code == UserWrapper.eFlag_Succ then
		result = "success"
	elseif code == UserWrapper.eFlag_QQ_UserCancel then
	elseif code == UserWrapper.eFlag_WX_UserCancel then
	elseif code == UserWrapper.eFlag_WX_NotInstall then
		display.pushToast(L("WXNotInstalledForShare"))
	elseif code == UserWrapper.eFlag_QQ_NotInstall then
		display.pushToast(L("QQNotInstalledForShare"))
	elseif code == UserWrapper.eFlag_WX_NotSupportApi or code == UserWrapper.eFlag_QQ_NotSupportApi then
		local platform = app.channelAPI:getWGPlatform()
		if platform == Enums.MSDK_PLATFORM.WX then
			display.pushToast(L("WXNotInstalledForShare"))
		elseif platform == Enums.MSDK_PLATFORM.QQ then
			display.pushToast(L("QQNotInstalledForShare"))
		else
			display.pushToast(L("tips_3000161"))
		end
	else
		
	end
    if result == "success" then
        self:_onShareSuccess()
    else
        self:_onShareFail()
    end
end


-- 好友信息缓存路径
function ChannelMsdk:_getFriendsCachePath()
	local openId = self:getOpenId()
	local name = "plat_friends_" .. openId
	return app:getStorePath() .. "/" .. name .. ".json", name
end

function ChannelMsdk:_cleanFriendCache()
	self._friendCache = nil

	local fileUtils = cc.FileUtils:getInstance()
	if self._headCachePath and fileUtils:isDirectoryExist(self._headCachePath) then
		fileUtils:removeDirectory(self._headCachePath)
	end
	self._headCachePath = nil
end

function ChannelMsdk:getHeadCachePathByOpenId(openId)
	if not openId then
		return ""
	end 
	if not self._headCachePath then
		self._headCachePath = app:getStorePath() .. "/head"
		print("self._headCachePath ", self._headCachePath)
		local fileUtils = cc.FileUtils:getInstance()
		if not fileUtils:isDirectoryExist(self._headCachePath) then
			fileUtils:createDirectory(self._headCachePath)
		end
	end
	return self._headCachePath.."/"..openId
end

function ChannelMsdk:_initFriendCache()
	-- 切换账号  清空self._friendCache

	if self._friendCache and self._friendCache.myInfo and self._friendCache.myInfo.openId ~= self:getOpenId() then
		self:_cleanFriendCache()
	end

	if not self._friendCache then
		local path, name = self:_getFriendsCachePath()
		if io.exists(path) then
			local content = cc.FileUtils:getInstance():getStringFromFile(path)
			local friendCache = json.decode(content)
			if friendCache then
				if os.time() - friendCache.expireTime >= 86400 then
					print("========>>>  friend info expire")
					self:_cleanFriendCache()
					return
				end
				self._friendCache = friendCache
			end
		end
	end
end

-- 保存 缓存信息
function ChannelMsdk:_saveFriendCache()
	if self._friendCache then
		local jsonStr = json.encode(self._friendCache)
		if jsonStr then
			local path, name = self:_getFriendsCachePath()
			print("save friend cache", path)
			io.writefile(path, jsonStr)
		end
	end
end





function ChannelMsdk:relationCallback(jsonRetStr)
	if jsonRetStr ~= "" then
		print("================= === =  json:", jsonRetStr)
		local friendCache = json.decode(jsonRetStr)
		if friendCache then
			-- 查询个人 
			if not self._friendCache then
				self._friendCache = {}
			end
			-- 这里不精确时间
			self._friendCache.expireTime = os.time()
			local selfOpenId = self:getOpenId()
			-- 查询 自己信息 和 查询好友信息返回同一个结构体
			if #friendCache == 1 and (friendCache[1].openId == "" or friendCache[1].openId == selfOpenId) then
				self._friendCache.myInfo = friendCache[1]
				self._friendCache.myInfo.openId = selfOpenId
				-- dump(self._friendCache.myInfo)
			else
				--手Q查询的同玩好友的结果是不包含自己的信息的；但微信查询的同玩好友的结果包含自己的信息。
				local friendsInfo = {}
				for k, v in pairs(friendCache) do
					if v.openId ~= "" and v.openId ~= selfOpenId then
						table.insert(friendsInfo, v)
					-- else
					-- 	self._friendCache.myInfo = v
					end
				end
				-- dump(friendsInfo)
				self._friendCache.friendsInfo = friendsInfo
			end
			EM:notify("onChannelFriendsUpdate")
			-- 避免保存2次
			if self._friendCache.friendsInfo ~= nil and self._friendCache.myInfo ~= nil then
				self:_saveFriendCache()
			end
		else
			print("===============decpde== === =  fail:")
		end
	else
		-- display.pushToast(L("tips_3000133"))
		print(L("tips_3000133"))
	end
end

function ChannelMsdk:httpdnsCallback(ips)
	print("httpdns Callback ip------->>>>"..ips)
	if ips == "0" then
		if self._domainCache and not self._httpdnsCount[self._domainCache] then
			self._httpdnsCount[self._domainCache] = 0
			print("httpdns self._domainCache", self._domainCache)
			print("httpdns self._httpdnsCount", self._httpdnsCount[self._domainCache])
		end
		if self._httpdnsCount[self._domainCache] and self._httpdnsCount[self._domainCache] < 1 then
			-- httpdns第一次解析失败，再解析一次
			self._httpdnsCount[self._domainCache] = self._httpdnsCount[self._domainCache] + 1
			self:getHostByNameAsync(self._domainCache, self._httpdnsCallback)
			return
		end
		if self._httpdnsCallback then
			self._httpdnsCallback()
		end
		self._httpdnsCount[self._domainCache] = nil
		self._domainCache = nil
		self._httpdnsCallback = nil
	elseif ips == "-1" then
		-- 使用了HTTP代理
		if self._httpdnsCallback then
			self._httpdnsCallback()
		end
		self._domainCache = nil
		self._httpdnsCallback = nil
	else
		if self._httpdnsCallback then
			local ipAry = string.split(ips, ";")
			self._httpdnsCallback(ipAry)
		end
		self._domainCache = nil
		self._httpdnsCallback = nil
	end
end
function ChannelMsdk:isPlatformInstalled(platform)
	if app:isAndroid() then
		local ok , ret = self.callJava("(I)Z", "isPlatformInstalled", platform)
		return ret
	elseif app:isIOS() then
		local ok , ret = self.callOC("isPlatformInstalled", {platform = platform})
		return ret
	end
	return false
end
	
-- 公会绑群相关接口
function ChannelMsdk:groupCallback(param)
	if not param then
		return
	end
	local retData = json.decode(param)
	if not retData then
		return
	end
	dump(retData)
	local funcName = retData.func
	local func = self._groupRetCallback[funcName]
	if func then
		func(retData)
	end
	self._groupRetCallback[funcName] = nil
end
-- qq
function ChannelMsdk:createQQGroup(guildInfo, callback)
	local ok
	self._groupRetCallback["OnCreateQQGroup"] = callback
	if app:isAndroid() then
		local guildJsonStr = json.encode(guildInfo)
		if guildJsonStr then
			ok  = self.callJava("(Ljava/lang/String;)V", "CreateQQGroup", guildJsonStr)
		else
			ok = false
		end
	elseif app:isIOS() then
		guildInfo.type = nil
		guildInfo.partition = nil
		ok  = self.callOC("CreateQQGroup", guildInfo)
	end

	if not ok then
		self._groupRetCallback["OnCreateQQGroup"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:queryQQGroupInfo(groupId, callback)
	if not groupId then
		return
	end
	local ok
	self._groupRetCallback["OnQueryQQGroupInfo"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;)V", "QueryQQGroupInfo", groupId)
	elseif app:isIOS() then
		ok  = self.callOC("QueryQQGroupInfo", {groupId = groupId})
	end

	if not ok then
		self._groupRetCallback["OnQueryQQGroupInfo"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:joinQQGroup(guildInfo, groupId, callback)
	local ok
	self._groupRetCallback["OnJoinQQGroup"] = callback
	if app:isAndroid() then
		local guildJsonStr = json.encode(guildInfo)
		if guildJsonStr then
			ok  = self.callJava("(Ljava/lang/String;Ljava/lang/String;)V", "JoinQQGroup", guildJsonStr, groupId)
		else
			ok = false
		end
	elseif app:isIOS() then
		guildInfo.groupId = groupId
		guildInfo.type = nil
		guildInfo.partition = nil
		ok  = self.callOC("JoinQQGroup", guildInfo)
	end

	if not ok then
		self._groupRetCallback["OnJoinQQGroup"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:unbindQQGroup(guildInfo, callback)
	-- 由于msdk 那边客户端接口不支持 转移会长的操作 需要调用后台接口
	--[[
		local ok
		self._groupRetCallback["OnUnbindQQGroup"] = callback
		if app:isAndroid() then
			local guildJsonStr = json.encode(guildInfo)
			if guildJsonStr then
				ok  = self.callJava("(Ljava/lang/String;)V", "UnbindQQGroup", guildJsonStr)
			else
				ok = false
			end
		elseif app:isIOS() then
			ok  = self.callOC("UnbindQQGroup", guildInfo)
		end

		if not ok then
			self._groupRetCallback["OnUnbindQQGroup"] = nil
		else
			print("call native fail")
		end
	]]
	
	--
	self._groupRetCallback["OnUnbindQQGroup"] = callback
	local domain = self:getMsdkDomain()
	local url
	local appId = self:getAppId()
	local msdkKey = self:getMsdkKey()
	local openId = self:getOpenId()
	local timestamp = os.time()
	local key = msdkKey..timestamp
	local sig = cc.Crypto:MD5(key, false)
	local postData
	local domain = self:getMsdkDomain()
	url = string.format("/relation/unlink_groupv2?timestamp=%s&appid=%s&sig=%s&openid=%s&encode=2", 
	timestamp, appId, sig, openId)
	url = domain..url

	local platid = "1"
	if app.isAndroid() then
		platid = "1"
	elseif app.isIOS() then
		platid = "2"
	end
		
	postData = json.encode({
		accessToken = self:getQqAccessToken(),
		appid = appId,
		openid = openId,
		guild_id = guildInfo.guildId,
		zone_id = guildInfo.zoneId,
		platid = platid,
		roleid = guildInfo.roleId,
		guild_name = guildInfo.guildName,
		type = guildInfo.type,
		areaid = guildInfo.areaId,
	})
	print("http ===> ", url, postData)
	if not url then
		return nil
	end
	app.http.reqJsonData(url,function(response,errorMsg,code)
		local returnTable = {
			flag = 1,
			errorCode = 0,
			desc = "",
		}
		dump(response)
		if response and response.ret == 0 then
			returnTable.desc = response.message
			returnTable.flag = 0
		else
			if response  then
				local data = response.data
				if data then
					returnTable.errorCode = data.err_code
					returnTable.desc = response.err_msg
				end
				returnTable.flag = 1
			end
		end

		local callFunc = self._groupRetCallback["OnUnbindQQGroup"]
		if callFunc then
			callFunc(returnTable)
			self._groupRetCallback["OnUnbindQQGroup"] = nil
		end
	end,"POST",false, postData, true)
end


function ChannelMsdk:bindExistQQGroup(guildInfo, groupId, groupName, callback)
	local ok
	self._groupRetCallback["OnBindExistQQGroup"] = callback
	if app:isAndroid() then
		local guildJsonStr = json.encode(guildInfo)
		if guildJsonStr then
			ok  = self.callJava("(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "BindExistQQGroup", guildJsonStr, groupId, groupName)
		else
			ok = false
		end
	elseif app:isIOS() then
		guildInfo.groupId = groupId
		guildInfo.groupName = groupName
		guildInfo.type = nil
		guildInfo.partition = nil
		ok  = self.callOC("BindExistQQGroup", guildInfo)
	end

	if not ok then
		self._groupRetCallback["OnBindExistQQGroup"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:getQQGroupCode(guildInfo, callback)
	local ok
	self._groupRetCallback["OnGetQQGroupCode"] = callback
	if app:isAndroid() then
		local guildJsonStr = json.encode(guildInfo)
		if guildJsonStr then
			ok  = self.callJava("(Ljava/lang/String;)V", "GetQQGroupCode", guildJsonStr)
		else
			ok = false
		end
	elseif app:isIOS() then
		guildInfo.type = nil
		guildInfo.partition = nil
		ok  = self.callOC("GetQQGroupCode", guildInfo)
	end

	if not ok then
		self._groupRetCallback["OnGetQQGroupCode"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:queryQQBindGuild(groupId, tp, callback)
	local ok
	self._groupRetCallback["OnQueryQQBindGuild"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;I)V", "QueryQQBindGuild", groupId, tp)
	elseif app:isIOS() then
		ok  = self.callOC("QueryQQBindGuild", {groupId = groupId, tp = tp})
	end

	if not ok then
		self._groupRetCallback["OnQueryQQBindGuild"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:getQQGroupList(callback)
	local ok
	self._groupRetCallback["OnGetQQGroupList"] = callback
	if app:isAndroid() then
		ok  = self.callJava("()V", "GetQQGroupList")
	elseif app:isIOS() then
		ok  = self.callOC("GetQQGroupList")
	end

	if not ok then
		self._groupRetCallback["OnGetQQGroupList"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:remindGuildLeader(guildInfo, callback)
	local ok
	self._groupRetCallback["OnRemindGuildLeader"] = callback
	if app:isAndroid() then
		local guildJsonStr = json.encode(guildInfo)
		if guildJsonStr then
			ok  = self.callJava("(Ljava/lang/String;)V", "RemindGuildLeader", guildJsonStr)
		else
			ok = false
		end
	elseif app:isIOS() then
		ok  = self.callOC("RemindGuildLeader", guildInfo)
	end

	if not ok then
		self._groupRetCallback["OnRemindGuildLeader"] = nil
	else
		print("call native fail")
	end
end

--微信
function ChannelMsdk:queryWXGroupInfo(guildId, openIdList, callback)
	local ok
	self._groupRetCallback["OnQueryWXGroupInfo"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;Ljava/lang/String;)V", "QueryWXGroupInfo", guildId, openIdList)
	elseif app:isIOS() then
		local params = {
			guildId = guildId,
			openIdList = openIdList
		}
		ok  = self.callOC("QueryWXGroupInfo", params)
	end

	if not ok then
		self._groupRetCallback["OnQueryWXGroupInfo"] = nil
	else
		print("call native fail")
	end
end

function ChannelMsdk:createWXGroup(guildId, chatRoomName, chatRoomNickName, callback)
	local ok
	self._groupRetCallback["OnCreateWXGroup"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "CreateWXGroup", guildId, chatRoomName, chatRoomNickName)
	elseif app:isIOS() then
		local params = {
			guildId = guildId,
			chatRoomName = chatRoomName,
			chatRoomNickName = chatRoomNickName
		}
		ok  = self.callOC("CreateWXGroup", params)
	end

	if not ok then
		self._groupRetCallback["OnCreateWXGroup"] = nil
	else
		print("call native fail")
	end
end

function ChannelMsdk:joinWXGroup(guildId, chatRoomNickName, callback)
	local ok
	self._groupRetCallback["OnJoinWXGroup"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;Ljava/lang/String;)V", "JoinWXGroup", guildId, chatRoomNickName)
	elseif app:isIOS() then
		local params = {
			guildId = guildId,
			chatRoomNickName = chatRoomNickName
		}
		ok  = self.callOC("JoinWXGroup", params)
	end

	if not ok then
		self._groupRetCallback["OnJoinWXGroup"] = nil
	else
		print("call native fail")
	end
end


function ChannelMsdk:queryWXGroupStatus(guildId, tp, callback)
	local ok
	self._groupRetCallback["OnQueryWXGroupStatus"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;I)V", "QueryWXGroupStatus", guildId, tp)
	elseif app:isIOS() then
		local params = {
			guildId = guildId,
			tp = tp
		}
		ok  = self.callOC("QueryWXGroupStatus", params)
	end
	if not ok then
		self._groupRetCallback["OnQueryWXGroupStatus"] = nil
	else
		print("call native fail")
	end
end

function ChannelMsdk:unbindWXGroup(guildId, callback)
	local ok
	self._groupRetCallback["OnUnbindWXGroup"] = callback
	if app:isAndroid() then
		ok  = self.callJava("(Ljava/lang/String;)V", "UnbindWXGroup", guildId)
	elseif app:isIOS() then
		local params = {
			guildId = guildId,
		}
		ok  = self.callOC("UnbindWXGroup", params)
	end
	if not ok then
		self._groupRetCallback["OnUnbindWXGroup"] = nil
	else
		print("call native fail")
	end
end

-- 获取登录 渠道id
-- 优先使用本地缓存的登录渠道（需求 渠道号回写功能实现）
-- 
function ChannelMsdk:getTencentLoginChannelId()
	if app:isAndroid() then
		if not self._tencentLoginChannelId then
			local openId = self:getOpenId()
			local path = app:getStorePath() .. "/tencentLoginChannelId_"..openId
			if io.exists(path) then
				local content = cc.FileUtils:getInstance():getStringFromFile(path)
				self._tencentLoginChannelId = tostring(content)
			else
				local tencentLoginChannelId = self:getLoginChannelId()
				if tencentLoginChannelId then
					self._tencentLoginChannelId = tencentLoginChannelId
					io.writefile(path, tostring(tencentLoginChannelId))
				end
			end
		end
		return self._tencentLoginChannelId
	else
		return self:getLoginChannelId()
	end
end
-- 判断是否是腾讯内部渠道
function ChannelMsdk:isChannelIdFromTencent()
	if app:isAndroid() then
		if self._isChannelIdFromTencent  == nil then
			-- 数据来源于 腾讯 飞鹰推送 渠道号
			local tencentChannelIds = {
				["208"] = true,
				["2002"] = true,
				["2017"] = true,
				["2037"] = true,
				["2038"] = true,
				["20888"] = true,
				["888889"] = true,
				["10000144"] = true,
				["10000145"] = true,
				["10001975"] = true,
				["10002100"] = true,
				["10002369"] = true,
				["10002464"] = true,
				["10002465"] = true,
				["10005169"] = true,
				["10005272"] = true,
				["10005273"] = true,
				["10005274"] = true,
				["10005275"] = true,
				["10005276"] = true,
				["10005277"] = true,
				["10005278"] = true,
				["10005279"] = true,
				["10005280"] = true,
				["10005281"] = true,
				["10005282"] = true,
				["10005283"] = true,
				["10005284"] = true,
				["10005285"] = true,
				["10005286"] = true,
				["10005287"] = true,
				["10005288"] = true,
				["10005289"] = true,
				["10007713"] = true,
				["10007714"] = true,
				["10007715"] = true,
				["10007716"] = true,
				["10017854"] = true,
				["10021833"] = true,
				["10021842"] = true,
				["10021843"] = true,
				["10021844"] = true,
				["10021845"] = true,
				["10021846"] = true,
				["10021847"] = true,
				["10021848"] = true,
				["10021849"] = true,
				["10021850"] = true,
				["10021851"] = true,
				["10022307"] = true,
				["10022308"] = true,
				["10022309"] = true,
				["10022310"] = true,
				["10022311"] = true,
				["10022312"] = true,
				["10022313"] = true,
				["10022314"] = true,
				["10022315"] = true,
				["10022316"] = true,
				["10022805"] = true,
				["10023811"] = true,
				["10023812"] = true,
				["10023813"] = true,
				["10023814"] = true,
				["10023815"] = true,
				["10023816"] = true,
				["10023817"] = true,
				["10023818"] = true,
				["10023819"] = true,
				["10023820"] = true,
				["10027608"] = true,
				["10027609"] = true,
				["10027610"] = true,
				["10029217"] = true,
				["10029218"] = true,
				["10029219"] = true,
				["10029842"] = true,
				["10029854"] = true,
				["10029869"] = true,
				["10030144"] = true,
				["10030146"] = true,
				["10030147"] = true,
				["10030148"] = true,
				["10030149"] = true,
				["10030150"] = true,
				["10030151"] = true,
				["10030152"] = true,
				["10030154"] = true,
				["10030155"] = true,
				["10030156"] = true,
				["10030476"] = true,
				["10031280"] = true,
				["10031328"] = true,
				["10031329"] = true,
				["10031330"] = true,
				["10031331"] = true,
				["10032042"] = true,
				["10032043"] = true,
				["10032044"] = true,
				["10032045"] = true,
				["10032046"] = true,
				["10032047"] = true,
				["10032048"] = true,
				["10032049"] = true,
				["10032050"] = true,
				["10032883"] = true,
				["10032884"] = true,
				["10032885"] = true,
				["10032886"] = true,
				["10032887"] = true,
				["10032888"] = true,
				["10033476"] = true,
				["10033477"] = true,
				["10033478"] = true,
				["10033489"] = true,
				["10033490"] = true,
				["10033491"] = true,
				["10033492"] = true,
				["10033781"] = true,
				["10033782"] = true,
				["10033783"] = true,
				["10033784"] = true,
				["10035116"] = true,
				["10035117"] = true,
				["10035118"] = true,
				["10035119"] = true,
				["10035120"] = true,
				["200000009"] = true,
				["200000101"] = true,
				["200000102"] = true,
				["200000103"] = true,
			}
			local id = self:getTencentLoginChannelId()
			if id then
				self._isChannelIdFromTencent = tencentChannelIds[id] == true
			end
		end
		return self._isChannelIdFromTencent
	else
		return true
	end
end

-- 获取登录之前唤起 游戏标记
function ChannelMsdk:getWakeupFlagBeforeLoginFlag()
	local ok = false
	local ret = -1
	if app:isAndroid() then
		ok, ret = self.callJava("()I","getWakeupFlagBeforeLoginFlag")
	elseif app:isIOS() then
		ok, ret = self.callOC("getWakeupFlagBeforeLoginFlag")
	end
	return ret
end

function ChannelMsdk:setWakeupFlagBeforeLoginFlag(flag)
	local ok = false
	if app:isAndroid() then
		ok, ret = self.callJava("(I)V","setWakeupFlagBeforeLoginFlag")
	elseif app:isIOS() then
		ok, ret = self.callOC("setWakeupFlagBeforeLoginFlag", {flag = flag})
	end
end

function ChannelMsdk:getLastWakeUpPlatform()
	local ok = false
	local ret = -1
	if app:isAndroid() then
		ok, ret = self.callJava("()I","getLastWakeUpPlatform")
	elseif app:isIOS() then
		ok, ret = self.callOC("getLastWakeUpPlatform")
	end
	return ret
end

function ChannelMsdk:setLastWakeUpPlatform(platform)
	local ok = false
	if app:isAndroid() then
		ok, ret = self.callJava("(I)V","setLastWakeUpPlatform", platform)
	elseif app:isIOS() then
		ok, ret = self.callOC("setLastWakeUpPlatform", {platform = platform})
	end
end

-- 获取 唤起平台
function ChannelMsdk:_getWakeUpFromPlatform()
	return self:getLastWakeUpPlatform()
	-- if self._wakeUpFromPlatform then
	-- 	return self._wakeUpFromPlatform
	-- else
		
		-- if self:isWakeUpFromQQ() then
		-- 	return PLATFORM_QQ
		-- elseif self:isWakeUpFromWX() then
		-- 	return PLATFORM_WX
		-- end
	-- end
end


-- 获取大区标记
-- 返回 区服 ， 环境 -- 1 正式服 2 抢先 3 体验  测试
function ChannelMsdk:getArea()
	local testChannel = cc.Configuration:getInstance():getValue('TEST_AREA')
	if testChannel and testChannel ~= "" then
		local t = string.split(testChannel, ";")
		return t[1], t[2]
	end

	local platform = app.channelAPI:getWGPlatform()
    if platform == Enums.MSDK_PLATFORM.WX then
		return "1", "1"
	elseif platform == Enums.MSDK_PLATFORM.QQ then
		return "2", "1"
	elseif platform == Enums.MSDK_PLATFORM.GUEST then 
		return "3", "1"
	end
	return "0", "1"
end


-- 
function ChannelMsdk:getMsdkDomain()
	local isTestEnv = false
	local testChannel = cc.Configuration:getInstance():getValue('TEST_AREA')
	if testChannel and testChannel ~= "" then
		isTestEnv = true
	end
	
	if isTestEnv then
		if app:isAndroid() then
			return "https://atest.ssl.msdk.qq.com/"
		elseif app:isIOS() then
			return "https://i.ssl.msdk.qq.com/"
		end
	else
		if app:isAndroid() then
			return "https://da.ssl.msdk.qq.com/"
		elseif app:isIOS() then
			return "https://i.ssl.msdk.qq.com/"
		end
	end
	return ""
end


function ChannelMsdk:jumpToAppShop()
    if app:isAndroid() then
        
	elseif app:isIOS() then
		local AppStoreAPPID = cc.Configuration:getInstance():getValue('AppStoreAPPID')
		if AppStoreAPPID and AppStoreAPPID ~= "" then
			local url = "https://itunes.apple.com/cn/app/id"..AppStoreAPPID
			device.openURL(url)
		end
		
        
    end

end

function ChannelMsdk:showStarReview()
	if app:isAndroid() then
	elseif app:isIOS() then
		self.callOC("showStarReview")
	end
end



function ChannelMsdk:getServerNameByIndex(serverIndex)
	if not serverIndex then
		return ""
	end
	serverIndex = serverIndex % 1000
	local platform = self:getWGPlatform()
	if PLATFORM_WX == platform then
		return L("WeChatServerName")..serverIndex..L("Server")
	elseif PLATFORM_QQ == platform then
		return L("QQServerName")..serverIndex..L("Server")
	else
		return serverIndex..L("Server")
	end
end

return ChannelMsdk